package com.googlecode.gwt.test.plugin.editors;


import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;

import com.googlecode.gwt.test.plugin.resourcesListner.CustomKeyWordsResource;
import com.googlecode.gwt.test.plugin.util.GwtCsvTestType;

public class KeyWords {

	private final String[] specialKeyWords = { "macro", "endmacro", "start" };

	private IProject currentProject;

	private Set<String> customKeywords;
	private Set<String> standardKeywords;

	public KeyWords(IProject currentProject) {
		this.currentProject = currentProject;
		refresh();
	}

	public void refresh() {
		try {
			loadStandardKeywords();
			loadCustomKeywords();
		} catch (Exception e) {
			throw new RuntimeException("Error while scanning project to find keywords", e);
		}
	}

	private void loadStandardKeywords() throws JavaModelException {
		standardKeywords = new HashSet<String>();
		IType clazz = GwtCsvTestType.getGwtCsvTestType(currentProject);
		for (IMethod m : clazz.getMethods()) {
			if (hasCsvMethodAnnotation(m)) {
				standardKeywords.add(m.getElementName());
			}
		}
	}

	private void loadCustomKeywords() throws JavaModelException {
		customKeywords = new HashSet<String>();
		IType root = GwtCsvTestType.getGwtCsvTestType(currentProject);
		ITypeHierarchy hierarchy = root.newTypeHierarchy(null);
		IType[] results = hierarchy.getAllSubtypes(root);
		for (IType type : results) {
			process(type);
		}
	}

	private void process(IType subType) throws JavaModelException {
		for (IMethod m : subType.getMethods()) {
			if (hasCsvMethodAnnotation(m)) {
				customKeywords.add(m.getElementName());
				CustomKeyWordsResource resource = ProjectPluginProperty.getInstance().getCustomKeyWordsResource(currentProject);
				resource.put(m.getElementName(), subType);
			}
		}
	}

	private boolean hasCsvMethodAnnotation(IMethod m) throws JavaModelException {
		for (IAnnotation annotation : m.getAnnotations()) {
			if (annotation.getElementName().contains("CsvMethod"))
				return true;
		}
		return false;
	}

	public String[] getSpecialKeyWords() {
		return specialKeyWords;
	}

	public Set<String> getKEYWORDS() {
		return standardKeywords;
	}

	public Set<String> getCustomKeywords() {
		return customKeywords;
	}

	public void setCUSTOM_MACROS(Set<String> custom_macros) {
		CUSTOM_MACROS = custom_macros;
	}

	public void setCUSTOM_MACROS(List<String> custom_macros) {
		CUSTOM_MACROS = new HashSet<String>(custom_macros);
	}

	public String[] getCUSTOM_MACROS() {
		return CUSTOM_MACROS.toArray(new String[0]);
	}

	public Set<String> getCUSTOM_MACROS_SET() {
		return CUSTOM_MACROS;
	}

	private Set<String> CUSTOM_MACROS = new HashSet<String>();

}
